package com.chatplus.application.service.pay.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.chatplus.application.client.pay.domain.request.wechat.WeChatOrderPayRequest;
import com.chatplus.application.client.pay.domain.response.InternalPayQueryResponse;
import com.chatplus.application.client.pay.domain.response.InternalPayResponse;
import com.chatplus.application.client.pay.domain.response.wechat.WechatOrderPayResponse;
import com.chatplus.application.common.exception.BadRequestException;
import com.chatplus.application.constant.PayConstants;
import com.chatplus.application.domain.entity.pay.PayRequestEntity;
import com.chatplus.application.enumeration.PayChannelEnum;
import com.chatplus.application.enumeration.PayStatusEnum;
import com.chatplus.application.service.pay.PayChannelServiceProvider;
import com.chatplus.application.service.pay.impl.wechat.WeChatPayApiService;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Map;

/**
 * 支付渠道业务逻辑实现（微信支付）
 *
 * <p>Table: t_pay_channel - 支付渠道</p>
 *
 * @author developer
 */
@Service(PayChannelServiceProvider.SERVICE_NAME_PRE + "WEI_XIN")
public class WeChatChannelServiceImpl extends PayChannelService {

    /**
     * 订单超时关闭时间 3分钟
     */
    private final static long TIMEOUT_EXPRESS_VALUE = 60 * 3;

    private final WeChatPayApiService weChatPayApiService;

    public WeChatChannelServiceImpl(WeChatPayApiService weChatPayApiService) {
        this.weChatPayApiService = weChatPayApiService;
    }

    DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss+08:00").withZone(ZoneId.of("Asia/Shanghai"));

    @Override
    public InternalPayResponse orderPay(PayRequestEntity payRequestEntity, String subject) {
        InternalPayResponse paymentPayResponse = new InternalPayResponse();
        WeChatOrderPayRequest weChatOrderPayRequest = new WeChatOrderPayRequest();
        weChatOrderPayRequest.setPayTransactionId(payRequestEntity.getPayTransactionId() + "");
        weChatOrderPayRequest.setMoney(payRequestEntity.getTotalMoney());
        weChatOrderPayRequest.setSubject(subject);
        // 设置订单超时时间
        weChatOrderPayRequest.setExpireTime(DTF.format(LocalDateTime.now().plusSeconds(180)));
        WechatOrderPayResponse wechatOrderPayResponse = weChatPayApiService.orderPay(weChatOrderPayRequest);
        if (wechatOrderPayResponse == null) {
            throw new BadRequestException("微信支付失败-请联系管理员处理");
        }
        paymentPayResponse.setActionUrl(wechatOrderPayResponse.getCodeUrl());
        payRequestEntity.setAppId(wechatOrderPayResponse.getAppId());
        return paymentPayResponse;
    }

    @Override
    public InternalPayQueryResponse queryOrderPay(PayRequestEntity payRequestEntity) {
        InternalPayQueryResponse queryOrderPayResponse = null;
        try {
            WxPayOrderQueryV3Result result = weChatPayApiService.queryOrderPay(payRequestEntity);
            queryOrderPayResponse = new InternalPayQueryResponse();
            String tradeStatus = result.getTradeState();
            switch (tradeStatus) {
                case PayConstants.Wechat.TRADE_SUCCESS:
                    String successTime = result.getSuccessTime();
                    Instant payTime = ObjectUtil.defaultIfEmpty(successTime,
                            () -> DateUtil.parse(successTime).toInstant(), Instant.now());
                    queryOrderPayResponse.setPaySuccessAt(payTime);
                    queryOrderPayResponse.setPayStatusEnum(PayStatusEnum.SUCCESS);
                    String payerInfo = StringUtils.trimToEmpty(result.getPayer().getOpenid());
                    String bankType = result.getBankType();
                    queryOrderPayResponse.setTradeTransactionId(result.getTransactionId());
                    queryOrderPayResponse.setPayerInfo(payerInfo+"|"+bankType);
                    break;
                // 如果交易关闭|结束，不处理支付结果，但是不报错，消费掉队列消息
                case PayConstants.Wechat.TRADE_CLOSED:
                    if (result.getPayer() != null) {
                        queryOrderPayResponse.setPayerInfo(StringUtils.trimToEmpty(result.getPayer().getOpenid()));
                    }
                    queryOrderPayResponse.setPayStatusEnum(PayStatusEnum.FAIL);
                    break;
                default:
                    break;
            }
        } catch (WxPayException wxPayException) {
            // 如果支付单在微信端不存在
            if (wxPayException.getErrCode().equals(PayConstants.Wechat.ORDER_NOT_EXIST) ||
                    wxPayException.getErrCode().equals(PayConstants.Wechat.ORDERNOTEXIST)) {
                queryOrderPayResponse = new InternalPayQueryResponse();
                queryOrderPayResponse.setPayStatusEnum(PayStatusEnum.FAIL);
            }
        }
        return queryOrderPayResponse;
    }

    @Override
    public boolean verifySign(Map<String, String> params) {
        return true;
    }

    @Override
    public PayChannelEnum getChannel() {
        return PayChannelEnum.WEI_XIN;
    }

    @Override
    public String getLogo() {
        return "/img/wechat-pay.jpg";
    }
}
